#pragma once
#include <iostream>
#include <string>
#include <iomanip>
#include <math.h>
using namespace std;

template<class T>
class interval
{
private:
	T lower;
	T upper;
public:
	interval(){lower = upper = 0;}
	interval(T mean, double procent)
	{
		lower = mean - mean * procent / 100.0;
		upper = mean + mean * procent / 100.0;
	}
	T mean() {return (upper + lower) / 2;}
	double relative_error(){return abs((upper - lower) / mean);}
	double absolute_error(){return abs(upper - lower);}
	double percent_error(){return abs((upper - lower) / mean) * 100;}
	
	friend ostream& operator <<(ostream &out, interval<T> a)
	{
		out << "[" << a.lower << "," << a.upper << "]";
		return out;
	}
	
	friend interval<T> operator *(interval<T> &lop, interval<T> &rop)
	{
		interval<T> m;
		m.upper = max(max(lop.lower * rop.lower, lop.lower * rop.upper), max(lop.upper * rop.lower, lop.upper * rop.upper));
		m.lower = min(min(lop.lower * rop.lower, lop.lower * rop.upper), min(lop.upper * rop.lower, lop.upper * rop.upper));
		return m;
	}

	friend interval<T> operator +(interval<T> &lop, interval<T> &rop)
	{
		interval<T> m;
		m.lower = lop.lower + rop.lower;
		m.upper = lop.upper + rop.upper;
		return m;
	}

	friend interval<T> operator -(interval<T> &lop, interval<T> &rop)
	{
		interval<T> m;
		m.lower = lop.lower - rop.upper;
		m.upper = lop.upper - rop.lower;
		return m;
	}
	
	friend interval<T> operator /(interval<T> &lop, interval<T> &rop)
	{
		interval<T> m;
		if(rop.lower != 0 && rop.upper != 0)
		{
			m.upper = max(max(lop.lower / rop.lower, lop.lower / rop.upper), max(lop.upper / rop.lower, lop.upper / rop.upper));
			m.lower = min(min(lop.lower / rop.lower, lop.lower / rop.upper), min(lop.upper / rop.lower, lop.upper / rop.upper));
		}
		else
			cout << "DIVISION BY FUCKING ZERO!!!";
		return m;
	}
};

